package lxs.swift.verify.objectCheck;

import lxs.swift.verify.Verifies;
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;
import java.util.Collection;

public interface Check<T> {
    boolean get(T v);

    static <T> Check<T> isNull() {
        return Verifies::isNull;
    }

    static <T> Check<T> isEmpty() {
        return Verifies::isEmpty;
    }

    static <T> Check<T> isDefault() {
        return Verifies::isDefault;
    }

    static <T> Check<T> isEq(T value) {
        return (v) -> Verifies.isObjectEq(v, value);
    }

    static Check<String> isStartsWith(@NotNull String str) {
        return (v) -> v.startsWith(str);
    }

    static Check<String> isEndsWith(@NotNull String str) {
        return (v) -> v.endsWith(str);
    }

    static Check<String> isWrap(@NotNull String start, @NotNull String end) {
        return v -> {
            if (start.length() + end.length() < v.length()) {
                return false;
            }
            return v.startsWith(start) && v.endsWith(end);
        };
    }

    static Check<String> isContains(String str) {
        return (v) -> v.contains(str);
    }

    static Check<String> isMatches(String regex) {
        return (v) -> v.matches(regex);
    }

    static <T extends Comparable<T>> Check<T> isGt(T v) {
        return value -> value.compareTo(v) > 0;
    }

    static <T extends Comparable<T>> Check<T> isLt(T v) {
        return value -> value.compareTo(v) < 0;
    }

    static <T extends Comparable<T>> Check<T> isGte(T v) {
        return value -> value.compareTo(v) >= 0;
    }

    static <T extends Comparable<T>> Check<T> isLte(T v) {
        return value -> value.compareTo(v) <= 0;
    }

    static <T extends Comparable<T>> Check<T> isBetween(T start, T end) {
        return value -> value.compareTo(start) >= 0 && value.compareTo(end) <= 0;
    }

    @SafeVarargs
    static <T> Check<Collection<T>> isInclude(T... v) {
        return value -> value.containsAll(Arrays.asList(v));
    }

    @SafeVarargs
    static <T> Check<Collection<T>> isExclude(T... v) {
        return value -> !value.containsAll(Arrays.asList(v));
    }

    @SafeVarargs
    static <T> Check<Collection<T>> isIncludeAny(T... v) {
        return value -> {
            for (T t : v) {
                if (value.contains(t)) return true;
            }
            return false;
        };
    }

    @SafeVarargs
    static <T> Check<Collection<T>> isExcludeAny(T... v) {
        return value -> {
            for (T t : v) {
                if (!value.contains(t)) return true;
            }
            return false;
        };
    }
}
